package esmp.jtt808;

import common.utils.DataPackUtil;
import esmp.jtt808.model.DataPack;
import esmp.jtt808.model.terminal.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by dave on 18-7-15 下午9:34.
 */
public class DataPackParser {

    public static DataPack parse(byte[] bs) {
        List<Byte> list = new ArrayList<>(bs.length);
        for (int i = 1; i < bs.length - 1; i ++) { // 忽略标识符，并反转义
            if (bs[i] == 0x7d && bs[i + 1] == 0x01) {
                list.add((byte) 0x7d);
                i++;
            } else if (bs[i] == 0x7d && bs[i + 1] == 0x02) {
                list.add((byte) 0x7e);
                i++;
            } else {
                list.add(bs[i]);
            }
        }

        byte[] bytes = DataPackUtil.byteListToArray(list);
        DataPack<Object> pack = new DataPack<>();
        pack.setMsgId(DataPackUtil.readWord(bytes, 0));
        int params = DataPackUtil.readWord(bytes, 2);
        pack.setEncrypted((params & (1 << 10)) > 0);
        pack.setSplit((params & (1 << 13)) > 0);
        pack.setSim(DataPackUtil.readBCD(bytes, 4, 6));
        pack.setSequenceNo(DataPackUtil.readWord(bytes, 10));

        int bodyStart = 12;
        int bodyEnd = bytes.length - 1; // 去除检验位
        if (pack.isSplit()) {
            pack.setPackageCount(DataPackUtil.readWord(bytes, 12));
            pack.setPackageNo(DataPackUtil.readWord(bytes, 14));
            bodyStart = 16;
        }

        switch (pack.getMsgId()) {
            case 0x0001:
                pack.setBody(new TerminalCommonResp().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0002:
                pack.setBody(new TerminalHeartBeat().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0003:
                pack.setBody(new TerminalDeregister().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0100:
                pack.setBody(new TerminalRegister().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0102:
                pack.setBody(new TerminalAuth().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0104:
                pack.setBody(new TerminalParamQueryResp().decode(bytes, bodyStart, bodyEnd));
                break;
            case 0x0200:
                pack.setBody(new LocationReport().decode(bytes, bodyStart, bodyEnd));
                break;

        }
        pack.setChecksum(list.get(list.size() - 2));
        return pack;
    }

}
